<script setup>
  import { ArrowLeftBold, Cellphone, Connection, Message, Upload, UserFilled } from "@element-plus/icons-vue";
  import {onMounted, ref} from "vue";
  import VerifyCodeAlert from "@/components/user/UserInfoEditVerifyCodeAlert.vue";
  import { ElMessage } from "element-plus";
  import commonApi  from "@/api/common/index.js";
  import fileApi from '@/api/file/index.js';
  import userApi from '@/api/user/index.js';
  import LocalStoreUtil from "@/utils/LocalStoreUtil.js";
  import ObjectUtil from "@/utils/ObjectUtil.js";
  import ResponseUtil from "@/utils/ResponseUtil.js";
  import { useStore } from "@/store/index.js";
  import Return from "@/components/common/Return.vue";

  const store = useStore();

  // 避免状态库页面刷新值为空，挂载时从缓存中获取
  onMounted(() => {
    if (store.user.info.id === -1) {
      store.user.info = LocalStoreUtil.getUserInfo();
    }
  })

  // 用户头像上传 Input 文本框元素
  let user_avatar_ref = ref(null);

  // 用户信息编辑表单打开状态
  let isEdit = ref(false);
  // 校验验证码弹窗组件打开状态
  let isCheckAlert = ref(false);

  // 验证码发送按钮加载（防止多次提交）
  let verify_code_publish_loading = ref(false);

  // 验证码发送按钮加载（防止多次提交）
  let submit_loading = ref(false);

  // 用户头像上传按钮加载（防止多次提交）
  let user_avatar_upload_loading = ref(false);

  let user_info = ref(ObjectUtil.clearRef(LocalStoreUtil.getUserInfo()))

  // 用户信息编辑表单数据
  let edit_form = ref(null);
  const edit_form_init = () => {
    // 表单数据重置
    edit_form.value = ObjectUtil.clearRef({
      type: 0,
      title: '用户信息',
      avatar: '',
      input_info: []
    })
  }

  // 验证码重新发送计时器对象（用于手动终止计时器）
  let verify_code_reset_timer = null;
  const try_stop_timer = () => {
    if (verify_code_reset_timer) {
      clearInterval(verify_code_reset_timer);
    }
  }

  // 校验验证码子组件中需要的数据
  let children_data = {};

  // 通过函数向子组件中传值，这样才能让子组件动态获取到更改后的最新数据
  const get_data = () => {
    return {
      ...children_data
    }
  }



  // ============================= 以下部分为设计逻辑的 js 部分，以上部分为使用到的变量定义 =============================


  // 表单数据初始化
  edit_form_init();


  // 点击 头像上传 文本框事件，进入文件选择
  const to_upload_avatar = () => {
    user_avatar_ref.value.click();
  }


  // 用户头像上传，input 内容变更后触发的事件
  const upload_avatar = (event) => {
    // 获取到上传的文件
    const file = event.target.files[0];

    if (!file) return;

    // 向服务器请求，上传图片
    user_avatar_upload_loading.value = true;
    fileApi.imageUpload(1, file).then(response => {
      user_avatar_upload_loading.value = false;
      ResponseUtil.data(response).dispose(response => {
        if (response.code === '200') {
          edit_form.value.avatar = response.data.path;
        }
      })
    })
  }


  /**
   * 进入用户信息编辑表单
   * @param type 0用户信息编辑，1邮箱信息编辑，2手机信息编辑
   */
  const to_edit_form = (type) => {
    // 用户信息编辑表单数据重置
    edit_form_init();

    // 验证码提交按钮加载状态关闭
    verify_code_publish_loading.value = false;

    // 头像上传文本框，已选择内容清空
    user_avatar_ref.value.value = '';

    // 如果验证码发送计时器还在执行则关闭
    try_stop_timer();

    // 更新编辑表单类型
    edit_form.value.type = type;

    // 根据编辑类型展示不同用户信息编辑的文本框，0用户信息编辑，1邮箱信息编辑，2手机信息编辑
    switch (type) {
      case 0:
        edit_form.value.title = '用户信息';
        edit_form.value.avatar = store.user.info.avatar;  // 如果用户已经设置过头像，则表单中默认显示已经设置的头像
        edit_form.value.input_info.push(
            {
              id: 'input_0_1',
              label: '昵称',
              placeholder: '请输入您的自定义昵称',
              is_open_check: false,
              input_data: store.user.info.nickName,  // 如果用户已经设置过昵称，则表单中默认显示已经设置的昵称
            }
        )
        break;
      case 1:
        edit_form.value.title = '邮箱信息';
        edit_form.value.input_info.push(
            {
              id: 'input_1_1',
              label: '邮箱号',
              placeholder: '请输入正确的邮箱',
              is_open_check: true,
              verify_code_status: 0, // 验证码状态（0基础状态，1已发送，2重写发送，3验证失败，4验证通过）
              message: '点击进行验证码验证',
              input_data: store.user.info.email,  // 如果用户已经设置过邮箱，则表单中默认显示已经设置的邮箱
              check_key: ''
            }
        )
        break;
      case 2:
        edit_form.value.title = '手机信息';
        edit_form.value.input_info.push(
            {
              id: 'input_2_1',
              label: '手机号',
              placeholder: '请输入正确的手机',
              is_open_check: true,
              verify_code_status: 0, // 验证码状态（0基础状态，1已发送，2重写发送，3验证失败，4验证通过）
              message: '点击进行验证码验证',
              input_data: store.user.info.mobile,  // 如果用户已经设置过手机号，则表单中默认显示已经设置的手机号
              check_key: ''
            }
        )
        break;
    }
    isEdit.value = true;
  }


  // 修改 手机号/邮箱 时，请求发送验证码和唤醒验证码校验弹窗之前的 手机号/邮箱 校验逻辑
  const publish_verify_code_check = (data) => {
    let message = '';

    // 根据当前展示的编辑表单类型进行不同的判断逻辑
    switch (edit_form.value.type) {
      case 0:
        message = data !== null && data !== '' ? '' : '请输入昵称！';
        if (message !== '') return message;
        message = data !== store.user.info.mobile ? '' : '昵称无修改！';
        break;
      case 1:
        message = data !== null && data !== '' ? '' : '请输入邮箱！';
        if (message !== '') return message;
        message = data !== store.user.info.email ? '' : '新邮箱与原邮箱重复！';
        if (message !== '') return message;
        message = data.includes('@') ? '' : '非法邮箱格式！';
        break;
      case 2:
        message = data !== null && data !== '' ? '' : '请输入手机号码！';
        if (message !== '') return message;
        message = data !== store.user.info.mobile ? '' : '新手机号与原手机号重复！';
        break;
    }
    return message;
  }


  // 根据当前标记编导的类型，获取对应的验证码业务类型（同后端对应，发送和校验 验证码时需要是同一个，否正无法正常校验）
  const get_verify_code_work_type = () => {
    let work_type = -1;
    if (edit_form.value.type === 1) {
      work_type = 5;
    }
    if (edit_form.value.type === 2) {
      work_type = 4;
    }
    return work_type;
  }


  /**
   * 内部深度封装发送验证码请求，包含验证码校验组件数据和父组件数据的处理
   * @param target 验证码发送目标（邮箱/手机号）
   * @param index 区分编辑表单数据源 与 校验验证码按钮 对应关系，因为按钮是根据数据 [] 长度遍历出来的，所以 index 同时对应了 dom 元素 与 数据
   * @returns {Promise<boolean>} 验证码发送成功/失败结果
   */
  const inner_get_verify_code = async (target, index) => {
    if (verify_code_publish_loading.value) {
      ElMessage.warning('正在发送验证码，请勿频繁操作');
      return false;
    }
    // 避免异常情况，提前尝试一下关闭验证码倒计时定时器的执行
    try_stop_timer();

    // 发送按钮加载状态设置为开启
    verify_code_publish_loading.value = true;

    // 请求服务器，发送验证码，等待请求的方法，避免请求异常的情况
    let response = await commonApi.getVerifyCode(target, get_verify_code_work_type());

    // 请求发送验证码完成，将发送按钮加载状态恢复为关闭
    verify_code_publish_loading.value = false;

    // 判断验证码是否发送成功，只有验证码发送成功时才进行对应后续数据的处理逻辑
    let flat = response.code === '200';
    if (flat) {
      // 修改校验验证码按钮中的文字为重新发送的倒计时
      edit_form.value.input_info[index].message = '验证码已发送，60秒后可重新发送';

      // 修改验证码重新发送倒计时时间
      edit_form.value.input_info[index].verify_code_time = 60;

      // 开启一个新的计时器，进行重新发送时间的倒计时
      verify_code_reset_timer = setInterval(() => {
        // 判断重新发送倒计时时间是否为最后 1 秒
        if (edit_form.value.input_info[index].verify_code_time === 1) {
          // 最后一秒时关闭计时器
          try_stop_timer();

          // 将倒计时时间重置为未开始的标识值 -1
          edit_form.value.input_info[index].verify_code_time = -1;

          // 更新校验验证码按钮中的文字
          edit_form.value.input_info[index].message = '重新发送验证码';

          // 结束当前函数向下执行
          return;
        }
        // 非最后一秒时，正常进行倒计时
        edit_form.value.input_info[index].verify_code_time -= 1;
        edit_form.value.input_info[index].message = '验证码已发送，' + edit_form.value.input_info[index].verify_code_time + '秒后可重新发送';
      }, 1000);

      // 验证码发送成功之后，更新将要传递到校验验证码子组件内的数据对象为最新数据（通过函数传递的那个对象）
      children_data.workType = get_verify_code_work_type();  // 验证码的业务类型，用于校验使用，这里是根据当前编辑表单获取的固定值
      children_data.index = index;  // 文本框的遍历索引，这里传入的作用是为了完成验证时，通知父组件时，更改感知对应的验证按钮，因为验证按钮可能存在多个，但校验弹窗组件只有一个
      children_data.target = edit_form.value.input_info[index].input_data;
      children_data.second = edit_form.value.input_info[index].verify_code_time;  // 暂时无用

      // 打开校验验证码弹窗
      isCheckAlert.value = true;
    }

    // 返回验证码的发送结果
    return flat;
  }

  // 验证码按钮点击处理逻辑
  const verify_code_button_click = async (index) => {
    // 调用验证码发送前置校验逻辑，手机号/邮箱 为入参，返回值不为空则表示存在错误
    let check_message = publish_verify_code_check(edit_form.value.input_info[index].input_data);
    if (check_message !== '') {
      ElMessage.warning(check_message);
      return;
    }

    // 之后根据当前按钮的不同状态，执行不同的点击处理逻辑，verify_code_status = 0基础状态，1已发送，2重新发送，3验证失败，4验证通过

    switch (edit_form.value.input_info[index].verify_code_status) {
      // 当按钮状态为基础状态，首次点击时
      case 0:
        // 为初始状态时，直接请求服务器进行验证码的发送
        let flat = await inner_get_verify_code(edit_form.value.input_info[index].input_data, index);

        // 如果发送失败则跳出整段执行逻辑
        if (!flat) return;

        // 验证码发送成功，将校验验证码按钮状态修改为 1已发送 状态
        edit_form.value.input_info[index].verify_code_status = 1;
        break;

      // 当按钮状态为 验证码已发送时
      case 1:
        // 根据重新发送倒计时的时间判断是否是首次发送验证码或重新发送倒计时结束
        if (edit_form.value.input_info[index].verify_code_time === -1) {
          // 首次发送 或 重新发送等待时间结束 时，重新发送验证码
          let flat = await inner_get_verify_code(edit_form.value.input_info[index].input_data, index);
        }

        // 打开校验验证码弹窗
        isCheckAlert.value = true;

        // 验证码发送成功之后，更新将要传递到校验验证码子组件内的数据对象为最新数据（通过函数传递的那个对象）
        children_data.workType = get_verify_code_work_type();  // 验证码的业务类型，用于校验使用，这里是根据当前编辑表单获取的固定值
        children_data.index = index;  // 文本框的遍历索引，这里传入的作用是为了完成验证时，通知父组件时，更改感知对应的验证按钮，因为验证按钮可能存在多个，但校验弹窗组件只有一个
        children_data.target = edit_form.value.input_info[index].input_data;
        children_data.second = edit_form.value.input_info[index].verify_code_time;  // 暂时无用
        break;

      // 当按钮的状态为 重新发送时
      case 2:
        break;

      // 当按钮的状态为 验证失败，验证码校验未通过时
      case 3:
        break;

      // 当按钮的状态为 验证通过,验证码校验完成时
      case 4:
        break;
    }

  }


  /**
   * 子组件回调函数
   * @param type 0弹窗关闭，1验证通过，2验证失败，3验证码过期，重新发送
   * @param index input 元素索引下标，这里就用到该参数来便是 dom 元素 与 数据的对应关系了
   * @param check_key 验证通过标识
   */
  const alert_callback = (type = 0, index = 0, check_key = '') => {
    switch (type) {
      // 弹窗关闭操作
      case 0:
        // 父组件的验证码弹窗打开状态同步为 false
        isCheckAlert.value = false;
        break;

      // 验证码校验通过
      case 1:
        // 尝试关闭验证码倒计时计时器，避免按钮中的内容继续被修改为倒计时的重发所需时间
        try_stop_timer();

        // 父组件的验证码弹窗打开状态同步为 false
        isCheckAlert.value = false;

        // 更新验证码校验按钮的状态为校验通过，展示不同的按钮样式
        edit_form.value.input_info[index].verify_code_status = 4;

        // 保存校验通过的标识，后台会根据标识进行二次校验
        edit_form.value.input_info[index].check_key = check_key;

        // 更新校验验证码按钮中的内容
        edit_form.value.input_info[index].message = '已通过验证码校验';
        break;

      // 验证码校验失败
      case 2:
        // 尝试关闭验证码倒计时计时器，避免按钮中的内容继续被修改为倒计时的重发所需时间
        try_stop_timer();

        // 更新验证码校验按钮的状态为校验失败，展示不同的按钮样式
        edit_form.value.input_info[index].verify_code_status = 2;

        // 更新校验验证码按钮中的内容
        edit_form.value.input_info[index].message = '校验未通过，重新发送验证码';
        break;

      // 验证码过期，自动重新发送验证码
      case 3:
        // 尝试关闭验证码倒计时计时器，避免按钮中的内容继续被修改为倒计时的重发所需时间
        try_stop_timer();

        // 更新验证码校验按钮的状态为校验通过，展示不同的按钮样式
        edit_form.value.input_info[index].verify_code_status = 3;

        // 更新校验验证码按钮中的内容
        edit_form.value.input_info[index].message = '验证码过期，重新发送验证码';
        break;
    }
  }


  // 提交用户信息的编辑
  const user_edit_form_submit = () => {

    // 根据当前编辑标记表单的类型，进行不同信息的编辑接口调用，type = 0用户信息编辑，1邮箱信息编辑，2手机信息编辑
    switch (edit_form.value.type) {
      // 用户信息编辑，头像、昵称编辑
      case 0:
        // 基本参数校验，头像和昵称至少有一项进行了修改
        if (edit_form.value.avatar === store.user.info.avatar &&
        edit_form.value.input_info[0].input_data === store.user.info.nickName) {
          ElMessage.warning('未进行任何修改');
          return;
        }

        // 提交按钮加载状态开始，避免重复提交
        submit_loading.value = true;

        // 向服务器发送用户信息修改请求
        userApi.updateAvatarAndNickName(store.user.info.id, edit_form.value.input_info[0].input_data, edit_form.value.avatar).then(response => {
          ResponseUtil.data(response).dispose(response => {
            // 请求成功时，进行修改完成后的出来逻辑
            if (response.code === '200') {
              ElMessage.success('用户信息修改成功');

              // 关闭用户信息编辑表单
              isEdit.value = false;

              // 从缓存中获取未更新的用户信息缓存
              let userInfo = ObjectUtil.clearRef(LocalStoreUtil.getUserInfo());

              // 将当前请求可能会修改的信息设置进行更新（头像、昵称）
              userInfo.nickName = edit_form.value.input_info[0].input_data;
              userInfo.avatar = edit_form.value.avatar;

              // 将更新后的最新用户信息更新到缓存中
              LocalStoreUtil.setUserInfo({...userInfo});

              // 将可能会更新的头像更新到状态库
              store.user.info.avatar = userInfo.avatar;

              // 将可能会更新的昵称更新到状态库
              store.user.info.nickName = userInfo.nickName;
            }
          })
        })

        // 提交按钮加载状态关闭
        submit_loading.value = false;
        break;

      // 1邮箱信息编辑，邮箱编辑
      case 1:
        if (edit_form.value.input_info[0].check_key ==='') {
          ElMessage.error('未通过邮箱验证码验证！');
          return;
        }

        // 提交按钮加载状态开始，避免重复提交
        submit_loading.value = true;

        // 向服务器发起邮箱信息修改请求
        userApi.updateEmail(store.user.info.id, edit_form.value.input_info[0].input_data, edit_form.value.input_info[0].check_key).then(response => {
          ResponseUtil.data(response).dispose(response => {
            // 请求成功时，进行修改完成后的出来逻辑
            if (response.code === '200') {
              ElMessage.success('邮箱修改成功');

              // 关闭用户信息编辑表单
              isEdit.value = false;

              // 从缓存中获取未更新的用户信息缓存
              let userInfo = ObjectUtil.clearRef(LocalStoreUtil.getUserInfo());

              // 将当前请求可能会修改的信息设置进行更新（邮箱）
              userInfo.email = edit_form.value.input_info[0].input_data;

              // 将更新后的最新用户信息更新到缓存中
              LocalStoreUtil.setUserInfo({...userInfo});

              // 将可能会更新的邮箱更新到状态库
              store.user.info.email = userInfo.email;

            } else {
              // 失败时，将关键信息重置
              edit_form.value.input_info[0].check_key = '';  // 验证码校验通过标识
              edit_form.value.input_info[0].verify_code_status = 0;  // 校验验证码按钮状态
              edit_form.value.input_info[0].message = '点击进行验证码验证';  // 校验验证码按钮内容
            }
          })
        })

        // 提交按钮加载状态关闭
        submit_loading.value = false;
        break;

      // 手机信息编辑，手机号编辑
      case 2:
        if (edit_form.value.input_info[0].check_key ==='') {
          ElMessage.error('未通过邮箱验证码验证！');
          return;
        }

        // 提交按钮加载状态开始，避免重复提交
        submit_loading.value = true;

        // todo 向服务器发起邮箱信息修改请求

        // 提交按钮加载状态关闭
        submit_loading.value = false;
        break;
    }
  }


</script>

<template>
  <VerifyCodeAlert :is_open="isCheckAlert" :get_data="get_data" :callback="alert_callback"></VerifyCodeAlert>

  <!-- 上传头像的input -->
  <input type="file" hidden="hidden" accept="image/*" ref="user_avatar_ref" @change="upload_avatar($event)"/>

  <div class="background-image">
    <div class="background-shade">

      <Return :color="false"></Return>

      <div class="user-info-basic">

        <div :class="['user-info-list', isEdit ? 'enable-edit-animation':'un-enable-edit-animation']">
          <div class="not-basic-item">
            <div class="avatar-exhibition">
              <img :src="store.user.info.avatar === '' ? 'http://120.46.171.159:9000/biscuit-tag-page/avatar/default-avatar.jpeg' : store.user.info.avatar" alt="头像">
            </div>
            <div class="user-basic-info">
              <div class="user-basic-info-nickname">{{ store.user.info.nickName }}</div>
              <div class="user-basic-info-uid">UID：{{ store.user.info.uId }}</div>
            </div>
          </div>

          <div class="basic-item-group">
            <div class="basic-item-one" @click="to_edit_form(0)">
              <div class="basic-item-one-inner-icon" style="background-color: #0066ff">
                <el-icon>
                  <UserFilled />
                </el-icon>
              </div>
              <div class="basic-item-one-inner-body">用户信息</div>
            </div>
          </div>

          <div class="basic-item-group">
            <div class="basic-item-one" @click="to_edit_form(1)">
              <div class="basic-item-one-inner-icon" style="background-color: #602dff">
                <el-icon>
                  <Message />
                </el-icon>
              </div>
              <div class="basic-item-one-inner-body">邮箱信息</div>
            </div>
            <div class="basic-item-one"  @click="to_edit_form(2)">
              <div class="basic-item-one-inner-icon" style="background-color: #0066ff">
                <el-icon>
                  <Cellphone />
                </el-icon>
              </div>
              <div class="basic-item-one-inner-body">手机信息</div>
            </div>
          </div>

        </div>


        <div :class="['user-info-edit-basic', isEdit ? 'edit-from-open-animation':'edit-from-close-animation']">
          <div class="user-info-edit-header">
            <div class="user-info-edit-header-return" @click="isEdit = false">
              <el-icon>
                <ArrowLeftBold />
              </el-icon>
            </div>
            <div class="user-info-edit-header-title">用户信息 - {{ edit_form.title }}</div>
          </div>

          <div class="user-info-edit-from-body">
            <!-- 只有选择用户信息时显示 -->
            <div v-if="edit_form.type === 0" class="user-info-edit-avatar"
                 v-loading="user_avatar_upload_loading">
              <div v-if="edit_form.avatar === ''" class="user-info-edit-avatar-upload-icon" @click="to_upload_avatar">
                <el-icon>
                  <Upload />
                </el-icon>
              </div>
              <img v-if="edit_form.avatar !== ''"
                   @click="to_upload_avatar"
                   :src="edit_form.avatar === '' ? 'http://120.46.171.159:9000/biscuit-tag-page/avatar/default-avatar.jpeg' : edit_form.avatar" alt="上传头像"/>
              <span>上传新头像，仅支持 png、jpg 等图片格式</span>
            </div>

            <div class="user-info-edit-button" v-for="(data, index) in edit_form.input_info" :key="data.id">
              <div class="user-info-edit-button-input">
                <label>{{ data.label }}</label>
                <input type="text" :placeholder="data.placeholder" v-model="data.input_data">
              </div>

              <div v-if="data.is_open_check"
                   @click.stop="verify_code_button_click(index)"
                   :class="['user-info-edit-verify-code-check',
                   data.verify_code_status === 0 ? 'user-info-edit-verify-code-check-status-0':'',
                   data.verify_code_status === 1 ? 'user-info-edit-verify-code-check-status-1':'',
                   data.verify_code_status === 2 ? 'user-info-edit-verify-code-check-status-2':'',
                   data.verify_code_status === 3 ? 'user-info-edit-verify-code-check-status-3':'',
                   data.verify_code_status === 4 ? 'user-info-edit-verify-code-check-status-4':'']">
                <div class="user-info-edit-verify-code-check-icon">
                  <el-icon>
                    <Connection />
                  </el-icon>
                </div>
                <div class="user-info-edit-verify-code-check-text">
                  {{ data.message }}
                </div>
              </div>
            </div>

          </div>

          <div class="user-info-edit-button-basic">
            <button class="user-info-edit-button-submit" @click="user_edit_form_submit" v-loading="submit_loading">提交</button>
            <button class="user-info-edit-button-cancel" @click="isEdit = false" v-loading="submit_loading">取消</button>
          </div>

        </div>

      </div>

    </div>
  </div>
</template>

<style scoped>

  .user-info-basic {
    width: 100vw;
    height: 100vh;
    position: relative;
    background-color: white;
  }

  .user-info-list {
    width: 600px;
    height: 80%;
    overflow-y: scroll;
    position: absolute;
    top: 10%;
    transition: left .5s cubic-bezier(0.4, 0, 0.2, 1);
  }

  .not-basic-item {
    width: 100%;
    overflow: hidden;
    display: flex;
    align-items: center;
    margin-bottom: 32px;
  }
  
  .avatar-exhibition {
    width: 120px;
    height: 120px;
    border-radius: 50%;
    overflow: hidden;
  }
  .avatar-exhibition img {
    width: 100%;
  }
  
  .user-basic-info {
    overflow: hidden;
    margin-left: 16px;
  }

  .user-basic-info-nickname {
    font-size: 24px;
    color: rgb(58, 58, 58);
    margin-bottom: 4px;
  }
  .user-basic-info-uid {
    font-size: 13px;
    color: rgb(102, 102, 102);
    margin-top: 4px;
  }

  .basic-item-group {
    width: 100%;
    overflow: hidden;
    background-color: #f5f5f5;
    border-radius: 10px;
    margin-bottom: 24px;
  }
  .basic-item-group:last-of-type {
    margin-bottom: 0;
  }
  .basic-item-group>div:last-child .basic-item-one-inner-body {
    border: none;
    height: 30px;
  }

  .basic-item-one {
    width: 100%;
    height: 60px;
    display: flex;
    align-items: center;
    transition: background-color .2s;
  }
  .basic-item-one:hover {
    cursor: pointer;
    background-color: #eeeeee;
  }

  .basic-item-one-inner-icon {
    width: 30px;
    height: 30px;
    display: flex;
    justify-content: center;
    align-items: center;
    border-radius: 5px;
    color: white;
    font-size: 20px;
    margin-left: 18px;
  }
  .basic-item-one-inner-body {
    width: calc(100% - 30px - 20px - 18px - 18px);
    height: 60px;
    display: flex;
    align-items: center;
    font-size: 18px;
    color: rgb(58, 58, 58);
    margin-left: 20px;
    border-bottom: 1px solid rgb(218, 218, 218);
  }

  .user-info-edit-basic {
    width: 500px;
    height: 400px;
    padding: 14px 20px;
    position: absolute;
    top: 15%;
    left: calc(50%);
  }
  .user-info-edit-header {
    overflow: hidden;
    display: flex;
    align-items: center;
    height: 40px;
  }
  .user-info-edit-header-return {
    width: 26px;
    height: 26px;
    font-size: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: rgb(245, 245, 245);
    border-radius: 50%;
    color: rgb(68, 68, 68);
    transition: all .3s;
  }
  .user-info-edit-header-return:hover {
    cursor: pointer;
    color: rgb(58, 58, 58);
    background-color: rgb(230, 230, 230);
  }
  .user-info-edit-header-title {
    color: rgb(58, 58, 58);
    font-size: 21px;
    margin-left: 16px;
  }

  .user-info-edit-from-body {
    width: 100%;
    overflow: hidden;
    margin-top: 32px;
  }

  .user-info-edit-button {
    width: 100%;
    overflow: hidden;
  }

  .user-info-edit-button-input {
    width: 100%;
    overflow: hidden;
    padding-bottom: 12px;
  }
  .user-info-edit-button-input label {
    padding-left: 3px;
    font-size: 14px;
  }
  .user-info-edit-button-input label:after {
    content: '*';
    color: red;
    margin-left: 2px;
  }
  .user-info-edit-button-input input {
    border: none;
    outline: none;
    width: 100%;
    height: 46px;
    text-indent: 16px;
    font-size: 16px;
    color: rgb(58, 58, 58);
    border-radius: 6px;
    background-color: rgb(238, 238, 238);
    margin-top: 5px;
  }

  .user-info-edit-verify-code-check {
    width: 100%;
    height: 46px;
    margin-top: 12px;
    border-radius: 5px;
    display: flex;
    justify-content: center;
    align-items: center;
    color: rgb(58, 58, 58);
    transition: all .3s;
    cursor: pointer;
    user-select: none;
  }

  .user-info-edit-verify-code-check-icon {
    overflow: hidden;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 18px;
    margin: 0 5px;
  }
  .user-info-edit-verify-code-check-text {
    font-size: 15px;
    margin: 0 5px;
  }

  .user-info-edit-verify-code-check-status-0 {
    background-color: rgb(171, 174, 180);
    color: white;
  }
  .user-info-edit-verify-code-check-status-0:hover {
    opacity: 0.9;
  }
  .user-info-edit-verify-code-check-status-1 {
    background-color: rgba(64, 158, 255);
    color: white;
  }
  .user-info-edit-verify-code-check-status-1:hover {
    opacity: 0.9;
  }
  .user-info-edit-verify-code-check-status-2 {
    background-color: rgba(230, 162, 60);
    color: white;
  }
  .user-info-edit-verify-code-check-status-2:hover {
    opacity: 0.9;
  }
  .user-info-edit-verify-code-check-status-3 {
    background-color: rgba(245, 108, 108);
    color: white;
  }
  .user-info-edit-verify-code-check-status-3:hover {
    opacity: 0.9;
  }
  .user-info-edit-verify-code-check-status-4 {
    background-color: rgba(103, 194, 58);
    color: white;
    cursor: not-allowed;
  }

  .user-info-edit-avatar {
    overflow: hidden;
    position: relative;
    margin-bottom: 30px;
  }
  .user-info-edit-avatar>* {
    float: left;
  }
  .user-info-edit-avatar-upload-icon {
    width: 80px;
    height: 80px;
    background-color: #e0f0ff;
    color: #99aecd;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 32px;
    cursor: pointer;
  }
  .user-info-edit-avatar img {
    cursor: pointer;
    width: 80px;
  }
  .user-info-edit-avatar span {
    margin-left: 10px;
    color: rgb(168, 168, 168);
    font-size: 12px;
    position: absolute;
    bottom: 0;
    left: 82px;
  }
  
  .user-info-edit-button-basic {
    width: 100%;
    overflow: hidden;
    margin-top: 42px;
  }
  .user-info-edit-button-basic>button {
    border: none;
    padding: 9px 50px;
    margin-right: 20px;
    border-radius: 5px;
    font-size: 16px;
    cursor: pointer;
    transition: background-color .3s, color .3s;
  }
  .user-info-edit-button-submit {
    background-color: #0066ff;
    color: rgb(238, 238, 238);
  }
  .user-info-edit-button-submit:hover {
    background-color: #004ad9;
    color: white;
  }

  .user-info-edit-button-cancel {
    background-color: #f0f0f0;
    color: rgb(68, 68, 68);
    transition: background-color .3s, color .3s;
  }
  .user-info-edit-button-cancel:hover {
    background-color: #dadada;
    color: black;
  }
  


  .background-image {
    width: 100vw;
    height: 100vh;
    background-image: url("http://120.46.171.159:9000/biscuit-tag-page/global-background-image/1920_1080_1.jpg");
    background-size: 100%;
    background-position: center center;
    background-repeat: no-repeat;
    position: relative;
  }
  .background-shade {
    width: 100vw;
    height: 100vh;
    background-color: rgba(0, 0, 0, 0.1);
    backdrop-filter: blur(3px);
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .enable-edit-animation {
    left: 10%;
  }
  .un-enable-edit-animation {
    left: calc(50% - 300px);
    z-index: 2;
  }

  .edit-from-open-animation {
    animation-name: openAnimation;
    animation-duration: 1s;
    animation-fill-mode: forwards;
  }
  .edit-from-close-animation {
    display: none;
    animation-name: closeAnimation;
    animation-duration: 0.3s;
    animation-fill-mode: forwards;
  }

  @keyframes openAnimation {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }
  @keyframes closeAnimation {
    from {
      display: block;
      opacity: 1;
    }
    to {
      opacity: 0;
    }
  }

</style>